﻿/*
 * Most of this code was copied from http://www.worldwidetelescope.org/Docs/WorldWideTelescope_lcapi.html#Sample_Application
 * 
 * 
 * 
 *
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Xml; 

namespace TCSS_590_Team_Project___Visualize_Data_with_WorldWide_Telescope
{
    class WWT_Interface
    {
        string layerId;         //string GUID for the WWT Layer
        string lineBuffer;      //buffer to hold events until they are sent
        int lineCountInBuffer;  //Number of events in the buffer
        int totalEvents;        //Count of total events transmitted
        DateTime lastTimeBufferFlushed; //Time of last transmission, used to check for time-out

        public WWT_Interface()
        {
            initWWTLayer();
        }

        // +++++ by Ji +++++
        ~WWT_Interface()
        {
            deleteWWTLayer();
        }
        // +++++ by Ji +++++

        public void SendDataToWWT(System.Windows.Forms.DataGridViewRowCollection rows)
        {

        }

        public void SendDataToWWT(List<Form1.Tweet> tweets)
        {
            SendDataToWWT(tweets, false);
        }

        public void SendDataToWWT(List<Form1.Tweet> tweets, Boolean centerOnTweet)
        {
            //flushBufferToWWT("10/17/2012 08:00\t+47:35:50\t-122:19:41\t");
            // 
            // Send an UPDATE command 
            // 

            string time = "2009/01/09 03:44:38.8000";
            string lat = "10.437";  //"47.61993";
            string longitude = "56.992"; // "-122.348671";
            string depth = "0.01";
            string mag = "0.025";

            
            WebClient client = new WebClient();
            string url = "";
            string response = "";

            foreach (Form1.Tweet t in tweets)
            {
                if (centerOnTweet)
                {
                    url = string.Format("http://{0}:5050/layerApi.aspx?cmd=state&flyto={1}&instant=false&time={2}", getIP().ToString(), t.latitude + "," + t.longitude + ",0.03,0,0", t.orig_time);
                    response = client.UploadString(url, "");

                    System.Threading.Thread.Sleep(3000);
                }

                url = string.Format("http://{0}:5050/layerApi.aspx?cmd=update&id={1}&datetime={2}", getIP().ToString(), layerId, time);
                response = client.UploadString(url, t.orig_time + "\t" + t.latitude + "\t" + t.longitude + "\t" + depth + "\t" + mag + "\t" + t.text_content + "\t");

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(response);
                XmlNode node = doc["LayerApi"];
                string s = node.InnerText;

                // 
                // Handle an error situation 
                // 
                if (s.Contains("Error"))
                {
                    throw new Exception(s);
                }
            }
        }

        // 
        // Create a new WWT layer 
        // 
        private void initWWTLayer()
        {
            // 
            // Send a NEW command, extracting info from the data file and the UI 
            // 
            WebClient client = new WebClient();
            string startDate = ""; // "10/17/2012 08:00:00 AM";
            string name = "Point Simulation for TCSS 590 Project";
            string rate = "100";
            string frame = "Earth";
            string color = "FFFF0000";


            string url = string.Format("http://{0}:5050/layerApi.aspx?cmd=mode&lookat=Earth", getIP().ToString());
            string response = client.UploadString(url, "");
           

            //string url = string.Format("http://{0}:5050/layerApi.aspx?cmd=new&datetime={1}&timerate={2}&name={3}&frame={4}&color={5}&flyTo={6},{7},{8},{9},{10}&instant=True", getIP().ToString(), startDate, rate, name, frame, color, "47.61993", "-122.348671", "100", "0","0");
            url = string.Format("http://{0}:5050/layerApi.aspx?cmd=new&name={1}&frame={2}&color={3}", getIP().ToString(), name, frame, color);
            // field string below is delimited by tabs, not spaces 
            response = client.UploadString(url, "TIME\tLAT\tLON\tDEPTH\tMAG\tHOVERTEXT");

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(response);
            XmlNode node = doc["LayerApi"];
            XmlNode child = node.ChildNodes[0];
            layerId = child.InnerText;

            // 
            // Handle an error situation 
            // 
            if (layerId.Length != 36)
                throw new Exception("Invalid Layer Id received");

            url = string.Format("http://{0}:5050/layerApi.aspx?cmd=setprop&id={1}&propname=NameColumn&propvalue=5", getIP().ToString(), layerId);
            response = client.UploadString(url, "");

            url = string.Format("http://{0}:5050/layerApi.aspx?cmd=setprop&id={1}&propname=TimeSeries&propvalue=false", getIP().ToString(), layerId);
            response = client.UploadString(url, "");

            url = string.Format("http://{0}:5050/layerApi.aspx?cmd=setprop&id={1}&propname=PlotType&propvalue=Circle", getIP().ToString(), layerId);
            response = client.UploadString(url, "");

            url = string.Format("http://{0}:5050/layerApi.aspx?cmd=setprop&id={1}&propname=ScaleFactor&propvalue=0.015", getIP().ToString(), layerId);
            response = client.UploadString(url, "");
        }

        // 
        // Buffer the data and send it to WWT every N events or every T time units 
        // 
        private void flushBufferToWWT(string line) 
        { 
            const int FlushThresholdInEventCount = 100;     // Flush the buffer when this number of events is stored 
            const int FlushThresholdInSeconds = 2;          // Flush the buffer after this number of seconds has elapsed 
            // 
            // If line length is zero, this is the last transmission 
            // 
            if (line.Length > 0) 
            { 
                lineBuffer = lineBuffer + line + Environment.NewLine; 
                lineCountInBuffer++; 
            } 
            DateTime now = DateTime.Now; 

            // 
            // Send the buffer if flushing for the last time OR the buffer is full OR the timeout has been reached 
            // 
            if ((line.Length == 0 && lineCountInBuffer > 0) || 
                lineCountInBuffer == FlushThresholdInEventCount || 
                now.Subtract(lastTimeBufferFlushed) > TimeSpan.FromSeconds(FlushThresholdInSeconds)) 
            { 
                // 
                // Send an UPDATE command 
                // 
                WebClient client = new WebClient(); 

                string url = string.Format("http://{0}:5050/layerApi.aspx?cmd=update&id={1}", getIP().ToString(), layerId); 
                string response = client.UploadString(url, lineBuffer); 
                XmlDocument doc = new XmlDocument(); 
                doc.LoadXml(response); 
                XmlNode node = doc["LayerApi"]; 
                string s = node.InnerText; 

                // 
                // Handle an error situation 
                // 
                if (s.Contains("Error")) 
                { 
                    throw new Exception(s); 
                } 
                // 
                // Record a successful transmission 
                // 
                totalEvents += lineCountInBuffer; 

                // 
                // Clear the buffer 
                // 
                lineBuffer = string.Empty; 
                lastTimeBufferFlushed = now; 
                lineCountInBuffer = 0; 
            } 
        } 

        // 
        // Utility to extract IP address 
        // 
        private IPAddress getIP()
        {
            IPAddress ipAddress = IPAddress.Loopback;

            // Find IPV4 Address 

            foreach (IPAddress ipAdd in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (ipAdd.AddressFamily == AddressFamily.InterNetwork)
                {
                    if (checkForWWTWebServer(ipAdd))
                    {
                        ipAddress = ipAdd;
                        break;
                    }
                }
            }
            return ipAddress;
        }

        private bool checkForWWTWebServer(IPAddress address)
        {
            WebClient client = new WebClient();
            try
            {
                string version = client.DownloadString(string.Format("http://{0}:5050/layerapi.aspx?cmd=version", address.ToString()));
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(version);
                XmlNode node = doc["LayerApi"];

                if (node.OuterXml.Contains("Version"))
                {
                    // As version numbers are in the format xx.xx.xx.xx, an individual comparison of each
                    // number is necessary - a simple string comparison will give unreliable results

                    string[] versionNumbers = node.InnerText.Split('.');
                    if (versionNumbers[0].CompareTo("2") >= 0 &&
                        versionNumbers[1].CompareTo("8") >= 0)
                        return true;
                }
            }
            catch (Exception ex)
            {
                // handle exception 
            }
            return false;
        }

        public void DisplayWWTProperties()
        {
            WebClient client = new WebClient();

            /*  Get Properties for Debugging */
            string url = string.Format("http://{0}:5050/layerApi.aspx?cmd=getprops&id={1}", getIP().ToString(), layerId);
            string response = client.UploadString(url, "");
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(response);

            System.Windows.Forms.MessageBox.Show(response);

        }

        // ++++++++++ by Ji ++++++++++
        private void deleteWWTLayer()
        {
            // 
            // Send a DELETE command 
            // 
            WebClient client = new WebClient();
            string url = string.Format("http://{0}:5050/layerApi.aspx?cmd=delete&id={1}", getIP().ToString(), layerId);
            string response = client.UploadString(url, "");
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(response);
            XmlNode node = doc["LayerApi"];
            string s = node.InnerText;

            // 
            // Handle an error situation 
            // 
            if (s.Contains("Error"))
            {
                throw new Exception(s);
            }
        }
        // ++++++++++ by Ji ++++++++++
    }
}
